﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Snefru.CustomComponent;
using Snefru.Interfaces;
using Snefru.Managers;
using System.Net;
using System.Threading;
using Snefru.Params;
using Snefru.XmlObjects;
using Snefru.Enums;


namespace Snefru
{
    public partial class Main : Form
    {
        public static SnefruProgressBar PbLoading;
        public static RichTextBox TxtAttackResult;
        public static TreeView TvDbName;

        private ThreadStart Starter;
        private Thread attackThread;
        private string ConfirmationQuery = string.Empty;
        private String Query = string.Empty;
        private String QueryLenght = string.Empty;
        private List<QueryType> queryTypes;
        private InjectionQuery ConfirmationType;

        #region [c.tor]
        public Main()
        {
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
        }
        #endregion

        #region [Event Handler]
        private void FrmMain_Load(object sender, EventArgs e)
        {
            SetInitialValues();
        }
        private void BtnAttack_Click(object sender, EventArgs e)
        {
            if (UtilityManager.ValidateUrl(TxtTargetURL.Text))
            {
                ConfirmationType = ((InjectionQuery)CmbInformation.SelectedItem);

                if (!string.IsNullOrEmpty(ConfirmationType.Query))
                {
                    Control[] tabs = TabResult.Controls.Find(((InjectionQuery)CmbInformation.SelectedItem).Name, true);
                    if (tabs.Count() == 0)
                    {
                        TabPage TabAttack = new TabPage();
                        TabAttack.Padding = new Padding(3);
                        TabAttack.Size = new Size(726, 194);
                        TabAttack.UseVisualStyleBackColor = true;
                        TabAttack.Name = ((InjectionQuery)CmbInformation.SelectedItem).Name;
                        TabAttack.Text = ((InjectionQuery)CmbInformation.SelectedItem).Name;

                        PbLoading = new SnefruProgressBar();
                        PbLoading.Location = new Point(8, 226);
                        PbLoading.Name = "pbLoading";
                        PbLoading.Size = new Size(710, 23);
                        PbLoading.Style = ProgressBarStyle.Continuous;

                        if (ConfirmationType.InjectionQueryID == 2)
                        {
                            TxtAttackResult = new RichTextBox();
                            TxtAttackResult.BackColor = Color.White;
                            TxtAttackResult.BorderStyle = BorderStyle.None;
                            TxtAttackResult.Location = new Point(218, 6);
                            TxtAttackResult.ReadOnly = true;
                            TxtAttackResult.Size = new Size(500, 216);
                            TxtAttackResult.Text = string.Empty;

                            TvDbName = new TreeView();
                            TvDbName.Location = new System.Drawing.Point(8, 6);
                            TvDbName.Size = new System.Drawing.Size(205, 216);
                            TvDbName.BorderStyle = BorderStyle.None;
                            TvDbName.TabIndex = 18;
                            
                            TabAttack.Controls.Add(TvDbName);                            
                            TabAttack.Controls.Add(TxtAttackResult);
                            TabAttack.Controls.Add(PbLoading);
                            TabResult.Controls.Add(TabAttack);
                            TabResult.SelectedIndex = TabResult.SelectedIndex + 1;
                            

                            Starter = delegate { Attacking(); };
                            attackThread = new Thread(Starter);
                            attackThread.Start();
                        }
                        else
                        {
                            TxtAttackResult = new RichTextBox();
                            TxtAttackResult.BackColor = Color.White;
                            TxtAttackResult.BorderStyle = BorderStyle.None;
                            TxtAttackResult.Location = new Point(8, 6);
                            TxtAttackResult.ReadOnly = true;
                            TxtAttackResult.Size = new Size(710, 216);
                            TxtAttackResult.Text = string.Empty;

                            TabAttack.Controls.Add(TxtAttackResult);
                            TabAttack.Controls.Add(PbLoading);
                            TabResult.Controls.Add(TabAttack);
                            TabResult.SelectedIndex = TabResult.SelectedIndex + 1;

                            Starter = delegate { Attacking(); };
                            attackThread = new Thread(Starter);
                            attackThread.Start();
                        }
                    }
                }
                else
                {
                    MessageBox.Show("Please Select");
                }
            }
            else
            {
                TxtResult.Text += "\n[+] Invalid URL !";
            }
        }
        private void BtnAnalysis_Click(object sender, EventArgs e)
        {
            if (UtilityManager.ValidateUrl(TxtTargetURL.Text))
            {
                Starter = delegate { Analysis(); };
                new Thread(Starter).Start();
            }
            else
            {
                TxtResult.Text += "\n[+] Invalid URL !";
            }
        }
        private void BtnStop_Click(object sender, EventArgs e)
        {
                attackThread.Abort();
                TxtAttackResult.Text += "\n[-] Progress Abort !";
                BtnAttack.Enabled = true;
                BtnStop.Enabled = false;
        }
        private void CmbDatabaseType_SelectedIndexChanged(object sender, EventArgs e)
        {
            Int32 DBTypeValue = ((DatabaseInstance)this.CmbDatabaseType.SelectedItem).ID;
            UtilityManager.LoadInjectionQueriesCombo(CmbInformation, DBTypeValue);
        }
        private void RbPOST_CheckedChanged(object sender, EventArgs e)
        {
            TxtPostData.Enabled = true;
        }
        private void RbGET_CheckedChanged(object sender, EventArgs e)
        {
            TxtPostData.Enabled = false;
        }
        private void SettingsHttpHeaderTooltipMenuItem1_Click(object sender, EventArgs e)
        {
            FrmHttpHeaders httpHeaderForm = new FrmHttpHeaders();
            httpHeaderForm.Show();
        }
        private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }
        private void MnuGetTables_Click(object sender, EventArgs e)
        {
            Int32 DBTypeValue = ((DatabaseInstance)this.CmbDatabaseType.SelectedItem).ID;
            List<InjectionQuery>  InjectionQueries =  UtilityManager.LoadTableQuery(DBTypeValue,2);
            if (InjectionQueries.Count == 1)
            {
                string TableCountQuery = InjectionQueries[0].TableQuery.TableCountQuery;
                string TableNameQuery  = InjectionQueries[0].TableQuery.TableNameQuery;
                if (!string.IsNullOrEmpty(TableCountQuery) && !string.IsNullOrEmpty(TableNameQuery))
                {
                    MessageBox.Show(TableCountQuery);
                    MessageBox.Show(TableNameQuery);
                }    
            }
        }
        #endregion

        #region [Private Methods]
        private void SetInitialValues()
        {
            UtilityManager.LoadDatabaseInstancesCombo(CmbDatabaseType);
            BtnAttack.Enabled = false;
            BtnStop.Enabled = false;
            CmbInformation.Enabled = false;
            TxtPostData.Enabled = false;
        }
        private List<QueryType> GetQueryTypes()
        {
            List<QueryType> queryTypes = new List<QueryType>();
            Int32 DBTypeValue = ((DatabaseInstance)CmbDatabaseType.SelectedItem).ID;

            List<DatabaseInstance> databaseInstances = new SnefruQuerySettings().GetDetail(SnefruQuerySettings.XmlPath).DatabaseInstances;
            for (int i = 0; i < databaseInstances.Count; i++)
            {
                if (DBTypeValue == databaseInstances[i].ID)
                {
                    QueryLenght = databaseInstances[i].AttackingQuery.QueryLenght;
                    Query = databaseInstances[i].AttackingQuery.Query;
                    ConfirmationQuery = databaseInstances[i].ConfirmationQuery.Query;
                    for (int j = 0; j < databaseInstances[i].AttackingQuery.QueryTypes.Count; j++)
                    {
                        queryTypes.Add(databaseInstances[i].AttackingQuery.QueryTypes[j]);
                    }
                }
            }

            return queryTypes;

        }
        private void Analysis()
        {
            try
            {
                BtnAnalysis.Enabled = false;
                pbEffect.Value = 0;
                TxtResult.Text = string.Empty;
                TxtResult.Text = "[+] Analyzing !";

                queryTypes  = GetQueryTypes();

                if (!string.IsNullOrEmpty(ConfirmationQuery))
                {
                    if (queryTypes.Count > 0)
                    {
                        pbEffect.Maximum = queryTypes.Count;
                        for (int i = 0; i < queryTypes.Count; i++)
                        {
                            IAttackParams confirmationAttackParams = new ConfirmationAttackParams();
                            confirmationAttackParams.AttackID = queryTypes[i].AttackID;
                            confirmationAttackParams.AttackName = queryTypes[i].AttackName;
                            confirmationAttackParams.TargetUrl = TxtTargetURL.Text;
                            confirmationAttackParams.QueryPrefix = queryTypes[i].QueryPrefix;
                            confirmationAttackParams.Query = ConfirmationQuery;

                            ConfirmationAttackManager confirmationAttackManager = new ConfirmationAttackManager();

                            IAttackResult result = confirmationAttackManager.Attack(confirmationAttackParams);
                            
                            pbEffect.Value  = i;

                            if (result.StatusCode == HttpStatusCode.OK && result.TimeOfResponse.TotalSeconds >= 10.0)
                            {
                                TxtResult.Text += "\n[+] Vulnerability Confirmed " + confirmationAttackParams.AttackName + " !";
                                BtnAttack.Enabled = true;
                                BtnStop.Enabled = true;
                                CmbDatabaseType.Enabled = false;
                                CmbInformation.Enabled = true;
                                queryTypes[i].IsVulnerable = true;
                                break;
                            }
                            else
                            {
                                queryTypes[i].IsVulnerable = false;
                                TxtResult.Text += "\n[-] Not Vulnerable " + confirmationAttackParams.AttackName + "!";
                            }
                        }
                        pbEffect.Value = queryTypes.Count;
                        TxtResult.Text += "\n[+] Analyzing Finish !";
                        
                    }
                }
            }
            catch (Exception ex)
            {
                TxtResult.Text += "\n" + ex.Message;
            }
        }
        private void Attacking()
        {
            try
            {
                TxtAttackResult.Text = string.Empty;

                ConfirmationType = ((InjectionQuery)CmbInformation.SelectedItem);

                if (!string.IsNullOrEmpty(ConfirmationType.Query))
                {
                    if (queryTypes.Count > 0)
                    {
                        DateTime dtStart = DateTime.Now;
                        TxtAttackResult.Text = "[+] Attacking ! ";
                        TxtAttackResult.Text += "\n[+] Start Time : " + dtStart;

                        for (int i = 0; i < queryTypes.Count; i++)
                        {
                            if (queryTypes[i].IsVulnerable)
                            {
                                IAttackQueryParams parameters = new QueryAttackParams();
                                parameters.InjectionQuery = ConfirmationType;
                                parameters.TargetUrl = TxtTargetURL.Text;
                                parameters.AttackID = queryTypes[i].AttackID;
                                parameters.AttackName = queryTypes[i].AttackName;
                                parameters.QueryLenght = QueryLenght;
                                parameters.Query = Query;
                                parameters.QueryPrefix = queryTypes[i].QueryPrefix;

                                TxtAttackResult.Text += "\n[+] Trying the " + parameters.AttackName + " for " + ConfirmationType.Name + " !";

                                QueryAttackManager queryAttackManager = new QueryAttackManager();

                                IAttackQueryResult result = queryAttackManager.Attack(parameters);

                                if (!string.IsNullOrEmpty(result.ReturnValue))
                                {
                                    TxtAttackResult.Text += "\n[+] Result : " + result.ReturnValue;
                                    
                                    if (parameters.InjectionQuery.InjectionQueryID == 2)
                                    {
                                        if (TvDbName.InvokeRequired)
                                        {                                            
                                            TreeNode node = new TreeNode(result.ReturnValue);
                                            ContextMenuStrip mnu = new ContextMenuStrip();
                                            ToolStripMenuItem mnuGetTables = new ToolStripMenuItem("Get Tables");
                                            mnuGetTables.Click += new EventHandler(MnuGetTables_Click);
                                            mnu.Items.AddRange(new ToolStripItem[] { mnuGetTables });
                                            node.ContextMenuStrip = mnu;                                            
                                            Main.TvDbName.Invoke((MethodInvoker)(() => TvDbName.Nodes.Add(node)));
                                        }
                                    }
                                }
                                else
                                {
                                    TxtAttackResult.Text += "\n[-] Not Vulnerable " + parameters.AttackName + " !";
                                }
                            }
                        }
                        DateTime dtEnd = DateTime.Now;
                        TimeSpan tsAttackTotalTime = dtEnd.Subtract(dtStart); ;
                        TxtAttackResult.Text += "\n[+] End Time : " + dtEnd;
                        TxtAttackResult.Text += "\n[+] Attack Total Time : " + tsAttackTotalTime;
                        TxtAttackResult.Text += "\n[+] Attacking Finish !";
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }        
        #endregion
    }
}